package org.mybatis.enhance;

import com.kaka.util.ReflectUtils;
import org.apache.ibatis.builder.xml.XMLConfigBuilder;
import org.apache.ibatis.exceptions.ExceptionFactory;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.Properties;

/**
 * @author zkpursuit
 */
public class MybatisSqlSessionFactoryBuilder extends SqlSessionFactoryBuilder {

    @Override
    public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
        try {
            XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
            Configuration conf = new MybatisConfiguration();
            conf.setVariables(properties);
            Field field = ReflectUtils.getDeclaredField(XMLConfigBuilder.class, "configuration");
            if (field != null) {
                field.setAccessible(true);
                field.set(parser, conf);
            }
            field = ReflectUtils.getDeclaredField(XMLConfigBuilder.class, "typeAliasRegistry");
            if (field != null) {
                field.setAccessible(true);
                field.set(parser, conf.getTypeAliasRegistry());
            }
            field = ReflectUtils.getDeclaredField(XMLConfigBuilder.class, "typeHandlerRegistry");
            if (field != null) {
                field.setAccessible(true);
                field.set(parser, conf.getTypeHandlerRegistry());
            }
            return build(parser.parse());
        } catch (Exception e) {
            throw ExceptionFactory.wrapException("Error building SqlSession.", e);
        } finally {
            ErrorContext.instance().reset();
            try {
                inputStream.close();
            } catch (IOException e) {
                // Intentionally ignore. Prefer previous error.
            }
        }
    }

}

